package online.szlib.com.common.utils;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

import javax.imageio.ImageIO;

public class ImageHelper {

	public static final char[] CAPTCHARS = new char[] {
	        '3', '4', '5', '6', '7', '8',
	        'a', 'b', 'c', 'd', 'e', 'f', 'h', 'i', 'j', 'k', 'm',
	        'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y' };
	
	public static final int CODE_LENGTH = 4;
    public static final int IMAGE_WIDTH = 98;
    public static final int IMAGE_HEIGHT = 50;
    public static final Color COLOR_BACKGROUND = new Color(230, 230, 250);
    public static final Color COLOR_CHARACTER = new Color(0, 0, 0);
    public static final Font FONT_CHARACTER = new Font("Times New Roman", Font.BOLD, 34);
    public static final int COORDINATE_X = 10;
    public static final int COORDINATE_Y = 35;
    
    public static String generateCode(Random random) {
        int car = CAPTCHARS.length - 1;

        StringBuffer code = new StringBuffer();
        for (int i = 0; i < CODE_LENGTH; i++) {
            code.append(CAPTCHARS[random.nextInt(car) + 1]);
        }

        return code.toString();
    }	
    
    public static void output(OutputStream os, String registrationCode, Random random) throws IOException {
        BufferedImage bi = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_BYTE_INDEXED);
        Graphics2D graphics = bi.createGraphics();
        graphics.setBackground(COLOR_BACKGROUND);
        graphics.setColor(COLOR_BACKGROUND);
        graphics.fillRect(0, 0, bi.getWidth(), bi.getHeight());

        graphics.setColor(COLOR_CHARACTER);
        TextLayout textTl = new TextLayout(registrationCode, FONT_CHARACTER, new FontRenderContext(null, true, false));
        textTl.draw(graphics, COORDINATE_X, COORDINATE_Y);

        shear(graphics, bi.getWidth(), bi.getHeight(), COLOR_BACKGROUND, random);
      
        ImageIO.createImageOutputStream(os);
        ImageIO.write(bi, "jpg", os);
        graphics.dispose();
    }
    
    private static void shear(Graphics g, int w1, int h1, Color color, Random random) {
        shearX(g, w1, h1, color, random);
        shearY(g, w1, h1, color);
    }
    
    private static void shearX(Graphics g, int w1, int h1, Color color, Random random) {
        int period = random.nextInt(10) + 5;

        boolean borderGap = true;
        int frames = 15;
        int phase = random.nextInt(5) + 2;

        for (int i = 0; i < h1; i++) {
            double d = (double) (period >> 1) * Math.sin(
                    (double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);
            g.copyArea(0, i, w1, 1, (int) d, 0);
            if (borderGap) {
                g.setColor(color);
                g.drawLine((int) d, i, 0, i);
                g.drawLine((int) d + w1, i, w1, i);
            }
        }
    }
    
    private static void shearY(Graphics g, int w1, int h1, Color color) {
        int period = 10;

        boolean borderGap = true;
        int frames = 15;
        int phase = 7;

        for (int i = 0; i < w1; i++) {
            double d = (double) (period >> 1) * Math.sin(
                    (double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);
            g.copyArea(i, 0, 1, h1, 0, (int) d);
            if (borderGap) {
                g.setColor(color);
                g.drawLine(i, (int) d, i, 0);
                g.drawLine(i, (int) d + h1, i, h1);
            }
        }
    }
}
